Skip to main content

Order Component

Overriding Order Component

You can override default Order component by providing RegularOrder into uiOverrides: trading prop to the ChartReactApp

The Order component without Close button icon has the following properties:

interface RegularOrderProps {
readonly order: VisualOrder;
readonly className?: string;
readonly onSelect?: (id: string) => void;
readonly onDblClick?: (id: string) => void;
readonly onClick?: (id: string) => void;
readonly onDeselect?: (id: string) => void;
readonly onClose?: (id: string) => void;
readonly onDragStart?: (id: string) => void;
readonly createProtectionOrder?: (type: ProtectionOrderType, originalId: string) => void;
readonly takeProfitStopLossEnabled?: boolean;
readonly showPriceAsLabels?: boolean;
readonly horizontalLineWidth: number;
readonly isLineVisible?: boolean;
readonly onCreateOcoOrders?: () => void;
}
const OrderComponent = (props: OrderProps) => {
const {
children,
absoluteChildren,
side,
selected = false,
disabled = false,
className,
testId,
onClick,
onSelect,
onDblClick,
onDeselect,
withDeselectBtn = false,
data = {},
canCreateOCO = false,
onCreateOcoOrders,
} = props;

/* your code */

return (
<OrderContainerStyled {...dataAttrs} className={className} disabled={disabled} data-test-id={testId}>
{withDeselectBtn &&
deselectBtnTransition(
(styles, selected) =>
selected && (
<animated.div style={styles}>
<DeselectOrderButton onClick={onDeselectHandler} />
</animated.div>
),
)}
{absoluteChildren}
<OrderContainerInnerStyled onClick={onClickHandler} disabled={disabled} selected={selected}>
<Side side={side} />
{children}
{canCreateOCO &&
ocoBtnTransition(
(styles, selected) =>
selected && (
<animated.div style={styles}>
<CreateOcoOrdersButton onClick={onCreateOcoOrders} />
</animated.div>
),
)}
{/* withCloseBtn && <CloseOrderButton onClick={onCloseHandler} /> removed close Button */}
</OrderContainerInnerStyled>
</OrderContainerStyled>
);
};
export const OverridingOrderComponent = () => {
const onApiCreated = (api: ChartReactAPI) => {
api.onChartCreated((_chartId, _chartInstance) => {});
};
const chartReactAppContainerProps = { width: 800, height: 50 };

return (
<>
<ChartReactAppContainer {...chartReactAppContainerProps}>
<div className={'chart-react-container'} />
</ChartReactAppContainer>
<FlexContainer justifyContent={'flex-start'}>
<ChartReactAppWrapper
customConfig={{
trading: {
enabled: true,
},
}}
dependencies={{ ...CREATE_MOCK_PROVIDERS(), onApiCreated }}
uiOverrides={{
trading: {
RegularOrder,
},
}}
/>
</FlexContainer>
</>
);
};
Order component without close button

Source code:

import React, { MouseEvent, useCallback, useContext, useMemo, useRef } from 'react';
import { ChartReactAppContainer, ChartReactAppWrapper } from '../../../../src/components/ChartReactApp';
import { FlexContainer } from '../../../../src/components/FlexContainer';
import { OverrideProps } from '@dx-private/dxchart5-react/dist/chart/ui-overrides';
import { CREATE_MOCK_PROVIDERS } from '@dx-private/dxchart5-react-mock-providers';
import { ChartReactAPI } from '@dx-private/dxchart5-react/dist/chart/view-models/api/chart-react-api.view-model';
import { OrderProps } from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/order.component';
import { animated, useTransition } from '@react-spring/web';
import {
CreateOcoOrdersButton,
useOcoButtonsTransition,
} from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/create-oco-orders-button.component';
import {
getRegularOrderName,
isSelectSkippable,
renderSLTPShortcutSection,
skipSelectOrder,
} from '@dx-private/dxchart5-react/dist/chart/components/trading/order/order.functions';
import {
OrderContainerInnerStyled,
OrderContainerStyled,
OrderDelimiterStyled,
OrderSectionStyled,
} from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/order.styled';
import { DeselectOrderButton } from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/deselect-order-button.component';
import { Side } from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/side.component';
import { RegularOrderProps } from '@dx-private/dxchart5-react/dist/chart/components/trading/order/regular-order.component';
import {
checkOrderIsOnUIOnly,
getOrderPriceByType,
isProtection,
} from '@dx-private/dxchart5-react/dist/chart/model/trading/trading.model';
import {
AddSLOrderBtnStyled,
AddTPOrderBtnStyled,
OrderSLTPShortcutSectionStyled,
} from '@dx-private/dxchart5-react/dist/chart/components/trading/order/regular-order.styled';
import { TEST_IDS } from '@dx-private/dxchart5-react/dist/config/e2e/test-ids';
import { defaultOrderPriceFormatter } from '@dx-private/dxchart5-react/dist/chart/model/trading/order.model';
import { OrderLineStyled } from '@dx-private/dxchart5-react/dist/chart/components/trading/order/components/side.styled';
import { MultiChartComponentContext } from '@dx-private/dxchart5-react/dist/chart/components/multi-chart/multi-chart-context';
const OrderComponent = (props: OrderProps) => {
const {
children,
absoluteChildren,
side,
selected = false,
disabled = false,
className,
testId,
onClick,
onSelect,
onDblClick,
onDeselect,
withDeselectBtn = false,
data = {},
canCreateOCO = false,
onCreateOcoOrders,
} = props;
const timeoutId: React.MutableRefObject<number | null> = useRef(null);
const deselectBtnTransition = useTransition(selected && withDeselectBtn, {
config: {
duration: 150,
},
from: { position: 'absolute' as const, y: 0, x: 0, zIndex: -1, opacity: 0 },
enter: { x: -20, opacity: 1 },
leave: { x: 0, opacity: 0 },
delay: 150,
});
const ocoBtnTransition = useOcoButtonsTransition(selected && canCreateOCO);
const onDeselectHandler = useCallback(
(e: React.MouseEvent) => {
e.stopPropagation();
if (onDeselect) {
onDeselect();
}
},
[onDeselect],
);
const onClickHandler = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent & DragEvent>) => {
e.stopPropagation();
timeoutId?.current && clearTimeout(timeoutId.current);
if (onClick && e.detail === 1) {
timeoutId.current = setTimeout(onClick, 200);
} else if (onDblClick && e.detail === 2) {
onDblClick();
}
if (onSelect && !isSelectSkippable(e)) {
onSelect();
} else {
skipSelectOrder(e, false);
}
},
[onSelect, onClick, onDblClick],
);
const dataAttrs = useMemo(
() => Object.entries(data).reduce((acc, [k, v]) => ({ ...acc, [`data-${k}`]: v }), {}),
[data],
);
return (
<OrderContainerStyled {...dataAttrs} className={className} disabled={disabled} data-test-id={testId}>
{withDeselectBtn &&
deselectBtnTransition(
(styles, selected) =>
selected && (
<animated.div style={styles}>
<DeselectOrderButton onClick={onDeselectHandler} />
</animated.div>
),
)}
{absoluteChildren}
<OrderContainerInnerStyled onClick={onClickHandler} disabled={disabled} selected={selected}>
<Side side={side} />
{children}
{canCreateOCO &&
ocoBtnTransition(
(styles, selected) =>
selected && (
<animated.div style={styles}>
<CreateOcoOrdersButton onClick={onCreateOcoOrders} />
</animated.div>
),
)}
{/* withCloseBtn && <CloseOrderButton onClick={onCloseHandler} /> removed close Button */}
</OrderContainerInnerStyled>
</OrderContainerStyled>
);
};
export const RegularOrder = ({
chartReactAPIProps: _chartApi,
originalProps: props,
}: OverrideProps<RegularOrderProps>) => {
const {
order,
createProtectionOrder,
takeProfitStopLossEnabled,
showPriceAsLabels,
onClose,
onDeselect,
onSelect,
onClick,
onDblClick,
isLineVisible = true,
horizontalLineWidth,
onCreateOcoOrders,
} = props;
const { localization } = useContext(MultiChartComponentContext);
const { disabled, selected, model, marketPrice } = order;
const { id, side, quantity, orderType, limitPrice, stopPrice } = model;
const [isSLLinked, isTPLinked] =
!isProtection(order.model) && order.model.protectionOrderIds
? order.model.protectionOrderIds.map(id => !!id && !checkOrderIsOnUIOnly(id))
: ([false, false] as const);
const [showSLBtn, showTPBtn] =
!isProtection(order.model) && order.model.protectionOrderIds
? order.model.protectionOrderIds.map(id => Boolean(id))
: [false, false];
const onSelectHandler = useCallback(() => onSelect && !selected && onSelect(id), [id, onSelect, selected]);
const onClickHandler = useCallback(() => onClick && onClick(id), [id, onClick]);
const onDblClickHandler = useCallback(() => onDblClick && onDblClick(id), [id, onDblClick]);
const onDeselectHandler = useCallback(() => onDeselect && onDeselect(id), [id, onDeselect]);
const onCloseHandler = useCallback(() => onClose && onClose(id), [id, onClose]);
const addTPOrderHandler = useCallback(
(e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) => {
e.stopPropagation();
createProtectionOrder && createProtectionOrder('tp', id);
},
[createProtectionOrder, id],
);
const addSLOrderHandler = useCallback(
(e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) => {
e.stopPropagation();
createProtectionOrder && createProtectionOrder('sl', id);
},
[createProtectionOrder, id],
);
const tpTransition = useTransition(selected && !showTPBtn, {
config: {
duration: 150,
},
from: { position: 'absolute' as const, y: 0, top: 0, left: '50%', zIndex: -1, x: '-50%', opacity: 0 },
enter: {
y: side === 'buy' ? -20 : 20,
opacity: 1,
},
leave: showTPBtn ? { opacity: 0 } : { y: 0, opacity: 0 },
});
const slTransition = useTransition(selected && !showSLBtn, {
config: {
duration: 150,
},
from: { position: 'absolute' as const, y: 0, top: 0, left: '50%', zIndex: -1, x: '-50%', opacity: 0 },
enter: {
y: side === 'buy' ? 20 : -20,
opacity: 1,
},
leave: showSLBtn ? { opacity: 0 } : { y: 0, opacity: 0 },
});
const renderSLTPButtons = useMemo(() => {
return (
<>
{tpTransition(
(styles, show) =>
show && (
<animated.div style={styles}>
<AddTPOrderBtnStyled onClick={addTPOrderHandler}>
{localization.trading.protectionOrders.addButtons.takeProfit}
</AddTPOrderBtnStyled>
</animated.div>
),
)}
{slTransition(
(styles, show) =>
show && (
<animated.div style={styles}>
<AddSLOrderBtnStyled onClick={addSLOrderHandler}>
{localization.trading.protectionOrders.addButtons.stopLoss}
</AddSLOrderBtnStyled>
</animated.div>
),
)}
</>
);
}, [
tpTransition,
slTransition,
addTPOrderHandler,
addSLOrderHandler,
localization.trading.protectionOrders.addButtons.stopLoss,
localization.trading.protectionOrders.addButtons.takeProfit,
]);
const price = getOrderPriceByType(orderType, limitPrice, stopPrice, marketPrice);
return (
<>
<OrderComponent
data={order.model.data}
canCreateOCO={order.model.canCreateOCO}
side={side}
disabled={disabled}
selected={selected}
testId={`${TEST_IDS.order_item}_${id}`}
onSelect={onSelectHandler}
onClick={onClickHandler}
onDblClick={onDblClickHandler}
onClose={onCloseHandler}
onDeselect={onDeselectHandler}
absoluteChildren={takeProfitStopLossEnabled && renderSLTPButtons}
onCreateOcoOrders={onCreateOcoOrders}
withDeselectBtn>
<OrderSectionStyled>{quantity}</OrderSectionStyled>
<OrderDelimiterStyled margin="both" />
<OrderSectionStyled>{`${getRegularOrderName(orderType, localization.trading)} ${
!showPriceAsLabels ? (order.formatter || defaultOrderPriceFormatter)(price) : ''
}`}</OrderSectionStyled>
{(isSLLinked || isTPLinked) && (
<>
<OrderDelimiterStyled margin="both" />
<OrderSLTPShortcutSectionStyled>
{renderSLTPShortcutSection(isSLLinked, isTPLinked)}
</OrderSLTPShortcutSectionStyled>
<OrderDelimiterStyled margin="both" />
</>
)}
</OrderComponent>
{isLineVisible && (
<OrderLineStyled x={'101%'} y={9.5} width={horizontalLineWidth} disabled={disabled} selected={selected} />
)}
</>
);
};
export const OverridingOrderComponent = () => {
const onApiCreated = (api: ChartReactAPI) => {
api.onChartCreated((_chartId, _chartInstance) => {});
};
const chartReactAppContainerProps = { width: 800, height: 50 };
return (
<>
<ChartReactAppContainer {...chartReactAppContainerProps}>
<div className={'chart-react-container'} />
</ChartReactAppContainer>
<FlexContainer justifyContent={'flex-start'}>
<ChartReactAppWrapper
customConfig={{
trading: {
enabled: true,
},
}}
dependencies={{ ...CREATE_MOCK_PROVIDERS(), onApiCreated }}
uiOverrides={{
trading: {
RegularOrder,
},
}}
/>
</FlexContainer>
</>
);
};

🔸 Position integration and overriding

Observing positions

The observePositions callback is scoped per instrument (symbol).

Each symbol has its own subscription and position mapping. Only updates for the subscribed symbol are received.

Unsubscribing

Always unsubscribe when switching symbols or disposing components to avoid memory leaks.

Subscriptions are tied to the lifecycle of the chart or instrument view, especially in dynamic setups.

Overriding the position widget

You can override the position widged via uiOverrides.trading, just like the order component.

  • Supported from version 5.13.5.

  • If the widget doesn't render or respond, ensure you're using v5.13.5 or later.

For additional guidance or sample setups, contact DXcharts Support.